import { IRect, IVec2 } from "../../util/Defined";
import { TypeUtil } from "../../util/TypeUtil";
import { Intersection } from "../Intersection";
import { Matrix } from "../math/Matrix";
import { BaseShape, ShapeType } from "./BaseShape";
import { BoxShape } from "./BoxShape";
import { CircleShape } from "./CircleShape";
import { PolygonShape } from "./PolygonShape";

/**
 * 矩形图形(不支持旋转,性能好)
 */
export class RectShape extends BaseShape implements IRect {

    protected _width: number;
    protected _height: number;
    protected _halfWidth: number;
    protected _halfHeight: number;

    get width() {
        return this._width;
    }

    set width(v: number) {
        this._width = v;
        this._halfWidth = v / 2;
    }

    get height() {
        return this._height;
    }

    set height(v: number) {
        this._height = v;
        this._halfHeight = v / 2;
    }

    /**
     * 设置宽高
     * @param width 
     * @param height 
     */
    setSize(width: number, height: number) {
        this.width = width;
        this.height = height;
        return this;
    }

    getType(): ShapeType {
        return ShapeType.rect;
    }

    update(pos: Readonly<IVec2>, trans?: Readonly<Matrix>): this {
        if (trans) {
            this.worldAABB.setPos(
                this.x - this._halfWidth,
                this.y - this._halfHeight
            );

            const scaleX = trans.getScaleX();
            const scaleY = trans.getScaleY();
            trans.transformPointN(this.worldAABB);
            this.worldAABB.setSize(Math.abs(this.width * scaleX), Math.abs(this.height * scaleY));
            if (scaleX < 0) {
                this.worldAABB.x -= this.worldAABB.width;
            }
            if (scaleY < 0) {
                this.worldAABB.y -= this.worldAABB.height
            }

            this.worldAABB.addPosTo(pos);
        } else {
            this.worldAABB.setRect(
                pos.x + this.x - this._halfWidth,
                pos.y + this.y - this._halfHeight,
                this._width,
                this._height,
            );
        }

        return this;
    }

    testCollide(shape: Readonly<BaseShape>): boolean {
        switch (shape.getType()) {
            case ShapeType.circle:
                return Intersection.rectCircle2(this.worldAABB, (shape as CircleShape).worldCircle);
            case ShapeType.rect:
                return Intersection.rectRect(this.worldAABB, shape.worldAABB);
            case ShapeType.box:
            case ShapeType.polygon:
                return Intersection.rectRect(this.worldAABB, shape.worldAABB)
                    && Intersection.rectPolygon(this.worldAABB, (shape as BoxShape | PolygonShape).worldPolygon);
        }

        throw new Error(`未实现碰撞方法：${TypeUtil.getCls(this).name} -> ${TypeUtil.getCls(shape).name}`);
    }

}